#include "stdafx.h"
#include "leudgrid/DebugCrash.h"
#include "leudgrid/EventQueue.h"
#include "leudgrid/MonitorIOCP.h"
#include "leudgrid/Application.h"

static LEUD::CrashHandler ch;
namespace LEUD
{
	Application::Application(){
		m_StopEvent = CreateEvent(NULL,FALSE,FALSE,"");
		m_WakeEvent = CreateEvent(NULL,FALSE,FALSE,"");
	}
	Application::~Application(){
		CloseHandle(m_StopEvent);
		CloseHandle(m_WakeEvent);
	}

	bool Application::AddEventHandle(HANDLE handle)
	{
		if( std::find(m_EventVector.begin(),m_EventVector.end(),handle) == m_EventVector.end() )
		{
			m_EventVector.push_back( handle );
		}
		return true;
	}
	bool Application::RemoveEventHandle(HANDLE handle)
	{
		m_EventVector.erase(std::find(m_EventVector.begin(),m_EventVector.end(),handle));
		return true;
	}

	void Application::Start(int argc,char** argv){
		UINT   ThreadID;
		m_ThreadHandle = (HANDLE)_beginthreadex(NULL,0,MainThread,this,0,&ThreadID);
	}
	void Application::Stop(){
		SetEvent(m_StopEvent);
	}
	int Application::QueryQuitState()
	{
		if( WAIT_OBJECT_0 == WaitForSingleObject(m_ThreadHandle,0) )
		{
			return 0;
		}
		return 1;
	}

	void Application::Wake(){
		SetEvent(m_WakeEvent);
	}

	int  Application::Run(){
		WSADATA wsaData;WSAStartup( MAKEWORD(2,2), &wsaData );

		__try{
			OnStart();
		}__except(UnhandledExceptionFilter(GetExceptionInformation())){
		}

		DWORD WaitTime = INFINITE;
		HANDLE event[MAXIMUM_WAIT_OBJECTS];
		DWORD  size = 0;
		event[size++] = m_StopEvent;
		event[size++] = m_WakeEvent;
		for( std::vector<HANDLE>::iterator pos = m_EventVector.begin();
			pos!= m_EventVector.end();
			++ pos )
		{
			if( size < MAXIMUM_WAIT_OBJECTS-1 )
			{
				event[size++] = *pos;
			}
		}
		while(WAIT_OBJECT_0 != WaitForMultipleObjects(size,event,FALSE,WaitTime)){
			__try{
				OnUpdate();
			}__except(UnhandledExceptionFilter(GetExceptionInformation())){
			}
		}

		__try{
			OnStop();
		}__except(UnhandledExceptionFilter(GetExceptionInformation())){
		}

		WSACleanup();
		return 0;
	}
	unsigned int __stdcall Application::MainThread( void* data ){
		Application* This = (Application*)data;
		return This->Run();
	}
	Application::ExeCommandReturn Application::ExeCommand(std::string cmd,std::string& result)
	{
		return EXECOMMAND_RETURN_NEXT;
	}
	std::string Application::Help(int argc, char** argv)
	{
		return "";
	}

}
